home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / linuxcon.000 / linuxcon / linuxconf-1.6 / translate / msgcomp.c < prev    next >
C/C++ Source or Header  |  1996-04-18  |  6KB  |  248 lines

  1. #include <stdarg.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <limits.h>
  6. #include <errno.h>
  7. #include "internal.h"
  8.  
  9. #ifdef UNIX
  10.     #define MAXIMUM_PATH    PATH_MAX
  11. #else
  12.     #define MAXIMUM_PATH    128
  13. #endif
  14.  
  15. #define MISSING_MESSAGE "-???-"
  16. /*
  17.     Print an error message in a popup
  18.     Stubs to avoid linking the world
  19. */
  20. void xconf_error (const char *msg, ...)
  21. {
  22.     va_list list;
  23.     va_start (list,msg);
  24.     vfprintf (stderr,msg,list);
  25.     va_end (list);
  26. }
  27.  
  28.  
  29.  
  30. /* #Specification: translation / principle
  31.     The translation mecanism used by linuxconf is fairly
  32.     different from other system in used. Most system use
  33.     an external dictionary which can be translated without
  34.     recompiling the source. Linuxconf use a similar setup
  35.     except the dictionary is updated from the source.
  36.  
  37.     First msgscan is used to produce/update dictionnaries by
  38.     scanning all source file. It looks for macros like
  39.  
  40.     #
  41.     MSG_U(ID,"english message")
  42.     #
  43.  
  44.     or already translated ones
  45.  
  46.     #
  47.     MSG_B(ID,"english message","french message")
  48.     #
  49.  
  50.     From that, it produce a dictionary.
  51.  
  52.     This disctionary is then compiled and produce one include
  53.     file per dictionary and a resource message file which
  54.     contain several dictionary.
  55.  
  56.     One program may very well used several
  57.     dictionary and a dictionary may be compiled in many
  58.     message resource file.
  59. */
  60.  
  61.  
  62. static const char *msgcomp_getmsg (
  63.     TR_STRING *t,
  64.     const char *lang)
  65. {
  66.     
  67.     const char *ret = NULL;
  68.     while (*lang != '\0'){
  69.         ret = t->getmsg(lang[0]);
  70.         if (ret != NULL) break;
  71.         lang++;
  72.     }
  73.     return ret;
  74. }
  75.  
  76. static const char *msgcomp_getmsg (
  77.     TR_STRING *t,
  78.     TR_STRINGS *trans,    // Alternative dictionary to use
  79.     const char *lang,
  80.     const char *sysname)    // Use to print error message
  81.                 // If NULL, no error needed
  82. {
  83.     const char *ret = NULL;
  84.     TR_STRING *tt = trans->getitem(t->getid());
  85.     if (tt != NULL)    ret = msgcomp_getmsg (tt,lang);
  86.     if (ret == NULL) ret = msgcomp_getmsg(t,lang);
  87.     if (ret == NULL && sysname != NULL){
  88.         fprintf (stderr,"Missing message %s, system %s\n"
  89.             ,t->getid(),sysname);
  90.     }
  91.     return ret;
  92. }
  93.  
  94. class TR_STRINGS_COMP{
  95. public:
  96.     TR_STRINGS ref;        // Reference dictionary
  97.     TR_STRINGS trans;    // Translation
  98.     /*~PROTOBEG~ TR_STRING_COMP */
  99.     /*~PROTOEND~ TR_STRING_COMP */
  100. };
  101.  
  102. static int msgcomp_write (
  103.     const char *outfile,
  104.     TR_STRINGS_COMP trs[],
  105.     char *sysnames[],
  106.     int nbsys,
  107.     char *lang)    // Language to generate
  108.             // Instead of being a letter, it is a string of
  109.             // letter. The first one is the prefered one
  110.             // the other are fallback if the first is missing
  111. {
  112.     int ret = -1;
  113.     FILE *fout = fopen (outfile,"wb");
  114.     if (fout == NULL){
  115.         fprintf (stderr,"Can't open file %s (%s)\n"
  116.             ,outfile,strerror(errno));
  117.     }else{
  118.         // We write the header
  119.         ret = 0;
  120.         BDICT_HEADER hd;
  121.         hd.magic = BDICT_MAGIC;
  122.         hd.version = BDICT_VERSION;
  123.         hd.nbsys = nbsys;
  124.         fwrite (&hd,sizeof(hd),1,fout);
  125.         long offset_msg = sizeof(hd);
  126.  
  127.         // Then the header of each system
  128.  
  129.          int i;
  130.         for (i=0; i<nbsys; i++){
  131.             TR_STRINGS_COMP *tr = trs + i;
  132.             BDICT_SYSTEM sys;
  133.             memset (&sys,0,sizeof(sys));
  134.             strcpy (sys.name,sysnames[i]);
  135.             sys.version = tr->ref.getversion();
  136.             sys.nbmsg = tr->ref.getnb();
  137.             fwrite (&sys,sizeof(sys),1,fout);
  138.             offset_msg += sizeof (BDICT_SYSTEM) + sys.nbmsg*sizeof(long);
  139.         }
  140.  
  141.         // Then the lookup table for each system
  142.         // offset_msg now point to the beginning of the raw messages
  143.         // area
  144.         for (i=0; i<nbsys; i++){
  145.             TR_STRINGS_COMP *tr = trs + i;
  146.             int n = tr->ref.getnb();
  147.             TR_STRINGS *trans = &tr->trans;
  148.             for (int m=0; m<n; m++){
  149.                 TR_STRING *t = tr->ref.getitem(m);
  150.                 fwrite (&offset_msg,sizeof(offset_msg),1,fout);
  151.                 const char *msg = msgcomp_getmsg (t,trans,lang
  152.                     ,sysnames[i]);
  153.                 if (msg == NULL) msg = MISSING_MESSAGE;
  154.                 char buf[10000];
  155.                 str_compile (msg,buf);
  156.                 offset_msg += strlen (buf)+1;
  157.             }
  158.         }
  159.         for (i=0; i<nbsys; i++){
  160.             TR_STRINGS_COMP *tr = trs + i;
  161.             int n = tr->ref.getnb();
  162.             TR_STRINGS *trans = &tr->trans;
  163.             for (int m=0; m<n; m++){
  164.                 TR_STRING *t = tr->ref.getitem(m);
  165.                 const char *msg = msgcomp_getmsg (t,trans,lang,NULL);
  166.                 if (msg == NULL) msg = MISSING_MESSAGE;
  167.                 char buf[10000];
  168.                 str_compile (msg,buf);
  169.                 int len = strlen (buf)+1;
  170.                 fwrite (buf,len,1,fout);
  171.             }
  172.         }
  173.         fclose (fout);
  174.     }
  175.     return ret;
  176. }
  177.  
  178.  
  179. int main (int _argc, char *_argv[])
  180. {
  181.     char *argv[200];
  182.     int argc = anlparm (_argc,_argv,argv);
  183.     int ret = -1;
  184.     if (argc < 4){
  185.         fprintf (stderr,"msgcomp -ppath [-ppath] resfile lang_select dictionary ...\n");
  186.     }else{
  187.         char **tbsys = (char**)malloc(argc*sizeof(char*));
  188.         ret = 0;
  189.         int a;
  190.         const char *paths[2];
  191.         paths[0] = paths[1] = "";
  192.         int nbpath = 0;
  193.         for (a=1; a<argc; a++){
  194.             char *arg = argv[a];
  195.             if (arg[0] == '-'){
  196.                 if (arg[1] == 'p'){
  197.                     if (nbpath == 2){
  198.                         fprintf (stderr,"Option -p may be used only twice\n");
  199.                     }else if (arg[2] == '\0'){
  200.                         a++;
  201.                         paths[nbpath++] = argv[a];
  202.                     }else{
  203.                         paths[nbpath++] = arg+2;
  204.                     }
  205.                 }else{
  206.                     fprintf (stderr,"Invalid option %s\n",arg);
  207.                 }
  208.             }else{
  209.                 break;
  210.             }
  211.         }
  212.         const char *res = argv[a++];
  213.         char *lang = argv[a++];
  214.  
  215.         TR_STRINGS_COMP *trs = new TR_STRINGS_COMP[argc];
  216.         for (int i=a; i<argc; i++){
  217.             char *syspath = argv[i];
  218.             TR_STRINGS_COMP *tr = trs + i - a;
  219.             char path[MAXIMUM_PATH];
  220.             sprintf (path,"%s%s.dic",paths[0],syspath);
  221.             printf ("Processing %s\n",path);
  222.             tr->ref.read (path);
  223.             char *pt = strrchr (syspath,'/');
  224.             if (pt != NULL) syspath = pt+1;
  225.             tbsys[i-a] = strdup(syspath);
  226.             if (tr->ref.getnb()==0){
  227.                 fprintf (stderr,"Empty dictionary %s\n"
  228.                     ,argv[i]);
  229.                 ret = -1;
  230.             }
  231.             if (nbpath == 2){
  232.                 sprintf (path,"%s%s.dic",paths[1],argv[i]);
  233.                 printf ("           %s\n",path);
  234.                 tr->trans.read (path);
  235.             }
  236.         }
  237.         if (ret != -1){
  238.             ret = msgcomp_write (res,trs,tbsys,argc-a,lang);
  239.         }else{
  240.             fprintf (stderr
  241.                 ,"**** There were some error(s)\n"
  242.                  "**** No message produced\n");
  243.         }
  244.     }
  245.     return ret;
  246. }
  247.  
  248.